package oleg; 

/**
 * Copyright 2008 Oleg Frenkel
 *
 * This file is part of PerfectSearch.
 *
 * PerfectSearch is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PerfectSearch is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PerfectSearch.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.io.*;
import java.util.*;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import javax.microedition.pim.*;

import oleg.lcdui.*;
import oleg.log.Logger;
import oleg.log.LogView;
import oleg.match.*;
import oleg.locale.LocaleManager;
import oleg.rms.RMSManager;

public class MainForm implements ITextModifiedListener, IKeyListener
{
  static private MainForm instance;

  private MainSearch mainSearch;
  private ContactView contactView;
  private ConfigureView configureView;
  private LogView logView;
  private WritingLangView writingLangView;
  private ContactUtils contUtils = new ContactUtils();
  private IMatcher matcher;

  private TextListCanvas mainScreen;
  private Command callCommand = new Command("Call", Command.ITEM, 1);
  private Command viewCommand = new Command("View", Command.ITEM, 2);
  private Command writingLangCommand = new Command("Writing Language", Command.ITEM, 11);
  private Command configureCommand = new Command("Configure", Command.ITEM, 12);
  private Command aboutCommand = new Command("About", Command.ITEM, 20);
  private Command showLogCommand = new Command("Show Log", Command.ITEM, 21);
  private Command exitCommand = new Command("Exit", Command.ITEM, 22);

  private Vector allContacts = new Vector();
//   private Vector matchingStartNameContacts = new Vector();
//   private Vector matchingContacts = new Vector();

  private int errCounter = 0;

  public MainForm(MainSearch mainSearch) {
    this.mainSearch = mainSearch;
    contactView = new ContactView(mainSearch);
    configureView = new ConfigureView(mainSearch);
    logView = new LogView(mainSearch);
    writingLangView = new WritingLangView(mainSearch);
    instance = this;
  }

  static public void showError(String msg) {
    Alert alert = new Alert("Error Occurred");
    alert.setString("Error: " + msg);
    alert.setTimeout(Alert.FOREVER);
    Display display = Display.getDisplay(instance.mainSearch);
    display.setCurrent(alert, display.getCurrent());
  }

  public void updateWritingLang() {
    mainScreen.updateWritingLang();
    matcher.clearCache();
  }

  public void updateInterface() {
    configureView.updateInterface();
    writingLangView.updateInterface();
    contactView.updateInterface();

    mainScreen.removeCommand(viewCommand);
//     mainScreen.removeCommand(callCommand);
    mainScreen.removeCommand(aboutCommand);
    mainScreen.removeCommand(configureCommand);
    mainScreen.removeCommand(writingLangCommand);
    mainScreen.removeCommand(showLogCommand);
    mainScreen.removeCommand(exitCommand);

    LocaleManager localeMgr = LocaleManager.instance();

    callCommand = new Command(localeMgr.getProperty(C.CALL), Command.ITEM, 1);
    viewCommand = new Command(localeMgr.getProperty(C.VIEW), Command.ITEM, 2);
    aboutCommand = new Command(localeMgr.getProperty(C.ABOUT), Command.ITEM, 20);
//     configureCommand = new Command("Configure", Command.ITEM, 12);
    writingLangCommand = new Command(localeMgr.getProperty(C.WRITING_LANGUAGE), Command.ITEM, 11);
    showLogCommand= new Command(localeMgr.getProperty(C.SHOW_LOG), Command.ITEM, 21);
    exitCommand= new Command(localeMgr.getProperty(C.EXIT), Command.ITEM, 22);

    mainScreen.addCommand(viewCommand);
//     mainScreen.addCommand(callCommand);
    mainScreen.addCommand(aboutCommand);
    mainScreen.addCommand(configureCommand);
    mainScreen.addCommand(writingLangCommand);
    mainScreen.addCommand(showLogCommand);
    mainScreen.addCommand(exitCommand);

    mainScreen.updateInterface();
  }

  public Canvas getForm() {
    if (mainScreen == null) {
      buildMainForm();
    }

    return mainScreen;
  }

  private void buildMainForm() {
    mainScreen = new TextListCanvas();

    // load pim lists
    PIM pim = PIM.getInstance();
//     String[] contactLists = pim.listPIMLists(PIM.CONTACT_LIST);
//     for (int i = 0; i < contactLists.length; i++) {
//       mainScreen.append("Contact List: " + contactLists[i] + "\n");
      try {
//         PIMList pimList = pim.openPIMList(PIM.CONTACT_LIST, PIM.READ_ONLY, 
//                                           contactLists[i]);
        PIMList pimList = pim.openPIMList(PIM.CONTACT_LIST, PIM.READ_ONLY);
        Enumeration items = pimList.items();
        while (items.hasMoreElements()) {
          allContacts.addElement(items.nextElement());
        }
      } catch (Throwable e) {
        mainScreen.append("Error loading PIM lists: " + e.getMessage());
      }
   
//     }

    mainScreen.setTextModifiedListener(this);
    mainScreen.setKeyListener(this);
//     mainScreen.addCommand(showLogCommand);
    updateInterface();
    mainScreen.addCommandListener(new MainFormCommandListener());

    matcher = MatcherFactory.getMatcher(allContacts);

    updateList();
  }

  private void updateList() {
    try {
      // First, delete all items except for lookTF
      mainScreen.deleteAll();

//       Logger.log("MainForm: inside for inputText: " + mainScreen.getInputText());

      // Update matching lists
      matcher.updateMatchingContacts(mainScreen.getInputText());
//       Logger.log("Passed matcher.updateMatchingContacts");

      // First display names starting with search text
      Vector matchingStartNameContacts = matcher.getMatchingStartNameContacts();
//       Logger.log("MainForm: matchingStartNameContacts: " + matchingStartNameContacts);
      for (int i = 0; i < matchingStartNameContacts.size(); i++) {
        Contact curCont = (Contact)matchingStartNameContacts.elementAt(i);
        mainScreen.append(curCont.getString(Contact.FORMATTED_NAME, 0));
      }

      // Now display all other matchings
      Vector matchingContacts = matcher.getMatchingContacts();
//       Logger.log("MainForm: matchingContacts: " + matchingContacts);
      for (int i = 0; i < matchingContacts.size(); i++) {
        Contact curCont = (Contact)matchingContacts.elementAt(i);
        mainScreen.append(curCont.getString(Contact.FORMATTED_NAME, 0));
      }
//       Logger.log("MainForm: end");
    } catch (Throwable e) {
      e.printStackTrace();
      Logger.log(e.toString());
      logView.showView();
    }
  }

  public void textModified(String newText) {
    updateList();
    updateDisplayText();
  }

  public void keyPressed(int keyCode) {
    if (keyCode < 0 && Canvas.FIRE == mainScreen.getGameAction(keyCode)) {
      // Make the call
      callSelectedNumber();
    }

    updateDisplayText();
  }

  private void updateDisplayText() {
    String newDisplayText = matcher.getDisplayText(getSelectedContact(),
                                                   mainScreen.getInputText());
    mainScreen.setDisplayText(newDisplayText);
  }

//   private void updateMatchingContacts() {
//     matchingStartNameContacts.removeAllElements();
//     matchingContacts.removeAllElements();

//     String inputText = mainScreen.getInputText().toUpperCase();
//     int padMode = mainScreen.getPadMode();

//     for (int i = 0; i < allContacts.size(); i++) {
//       Contact curCont = (Contact)allContacts.elementAt(i);

//       switch (matcher.matchContact(curCont, inputText, padMode)) {
//       case C.START_MATCH:
//         matchingStartNameContacts.addElement(curCont);
//         break;
//       case C.CONTAIN_MATCH:
//         matchingContacts.addElement(curCont);
//         break;
//       }
//     }
//   }

  private Contact getSelectedContact() {
    // Find Contact to call
    if (mainScreen.size() == 0) {
      return null;
    }

    int selIndex = mainScreen.getSelectedIndex();
    if (selIndex == -1) {
      return null;
    }

    Vector matchingStartNameContacts = matcher.getMatchingStartNameContacts();
    int startLength = matchingStartNameContacts.size();
    if (selIndex < startLength) {
      return (Contact) matchingStartNameContacts.elementAt(selIndex);
    } else {
      Vector matchingContacts = matcher.getMatchingContacts();
      return (Contact) matchingContacts.elementAt(selIndex - startLength);
    }

  }

  private void callSelectedNumber() {
    Contact selCont = getSelectedContact();
    if (selCont == null) {
      return;
    }

    Vector phones = contUtils.getValuesAsVector(selCont, Contact.TEL);
    if (phones.size() == 0) {
      return;
    }

    String telStr = (String)phones.elementAt(0);
    try {
      boolean res = mainSearch.platformRequest("tel:" + telStr);
      if (res) {
        // there are no resources in the device: midlet has to exit in order 
        // to place a call
        mainSearch.exitApplication();
        return;
      }
    } catch (Exception e) {
      throw new RuntimeException("Failed to call: " + e.getMessage());
    }
  }


  private class MainFormCommandListener implements CommandListener
  {
    public void commandAction(Command c, Displayable s) {
//       if (c == callCommand) {
//         callSelectedNumber();
//         return;
//       }

      if (c == viewCommand) {
        Contact selCont = getSelectedContact();
        if (selCont == null) {
          return;
        }
        contactView.showDetail(selCont);
        return;
      }

      if (c == aboutCommand) {
        LocaleManager localeMgr = LocaleManager.instance();

        Alert aboutAlert = new Alert(localeMgr.getProperty(C.ABOUT));
        aboutAlert.setString(localeMgr.getProperty(C.ABOUT_TXT));
//         aboutAlert.setString("PerfectSearch version 1.0\n\n" +
//                              "Copyright 2008 Oleg Frenkel\n\n" +
//                              "Comments are welcome at oleg.frenkel@gmail.com\n\n" +
//                              "If you like PerfectSearch, and would like to express " +
//                              "it, you might want to donate at paypal: oleg.frenkel@gmail.com");
        aboutAlert.setTimeout(Alert.FOREVER);
        Display display = Display.getDisplay(mainSearch);
        display.setCurrent(aboutAlert, display.getCurrent());
        return;
      }

      if (c == configureCommand) {
        configureView.showView();
        return;
//         Alert configureAlert = new Alert("Configure");
//         StringBuffer locales = new StringBuffer();
//         String[] allLocales = LocaleManager.instance().getAllLocaleNames();
//         for (int i = 0; i < allLocales.length; i++) {
//           locales.append(allLocales[i] + " ");
//         }
//         configureAlert.setString(locales.toString());
//         configureAlert.setTimeout(Alert.FOREVER);
//         Display display = Display.getDisplay(mainSearch);
//         display.setCurrent(configureAlert, display.getCurrent());
//         return;
      }

      if (c == writingLangCommand) {
        writingLangView.showView();
        return;
//         Alert configureAlert = new Alert("Configure");
//         StringBuffer locales = new StringBuffer();
//         String[] allLocales = LocaleManager.instance().getAllLocaleNames();
//         for (int i = 0; i < allLocales.length; i++) {
//           locales.append(allLocales[i] + " ");
//         }
//         configureAlert.setString(locales.toString());
//         configureAlert.setTimeout(Alert.FOREVER);
//         Display display = Display.getDisplay(mainSearch);
//         display.setCurrent(configureAlert, display.getCurrent());
//         return;
      }

      if (c == showLogCommand) {
//         Alert debugAlert = new Alert("Debug");
//         Runtime rt = Runtime.getRuntime();
//         long free = rt.freeMemory();
//         long total = rt.totalMemory();
//         Cache cache = Cache.instance();
//         debugAlert.setString("used: " + (((double)(total - free))/total) +
//                              "\ncache clear count: " + cache.getClearCount() +
//                              "\nmatcher class: " + matcher.getClass().getName());
//         debugAlert.setString(Logger.getLog());
//         debugAlert.setTimeout(Alert.FOREVER);
//         Display display = Display.getDisplay(mainSearch);
//         display.setCurrent(debugAlert, display.getCurrent());
        logView.showView();
        return;
      }

      if (c == exitCommand) {
        mainSearch.exitApplication();
        return;
      }
    }
  }

}
